package org.nuplay;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;

import javax.sound.midi.MidiDevice;
import javax.sound.midi.MidiMessage;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.Receiver;
import javax.sound.midi.ShortMessage;
import javax.sound.midi.Transmitter;
import javax.swing.*;

import com.illposed.osc.OSCMessage;

public class NuPlayMidiClient extends JFrame implements ActionListener, WindowListener {
	
	private DatagramSocket client_socket;
	private DatagramPacket packet;
	private JComboBox midi_devices_choose;
	private JComboBox midi_devices_out_choose;
	private JTextField ip_number_choose;
	private JButton connect_button;
	private boolean connected;
	private JLabel error_label;
	
	//
	private Transmitter midi_transmitter;
	private Receiver midi_receiver;
	private MidiDevice midi_device;
	private JComboBox channel;
	private NuPlaySend sender;
	
	public NuPlayMidiClient() {
		connected = false;
		try {
			UIManager.setLookAndFeel(
			        UIManager.getCrossPlatformLookAndFeelClassName());
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UnsupportedLookAndFeelException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		build_ui();
		init_midi_devices();
	}

	public void actionPerformed(ActionEvent arg0) {
		if (arg0.getSource() == connect_button) {
			if (connected) {
				disconnect("ready...");	
			} else {
				connect();
			}
		}
	}
	
	private void build_ui() {
		addWindowListener(this);
		getContentPane().setLayout( new BorderLayout() );

		
		
		
		JPanel topPanel = new JPanel();
		topPanel.setLayout( null );
		getContentPane().add( topPanel, BorderLayout.CENTER );
		
		JLabel label_midi_device = new JLabel("Which MIDI-in device to use?");
		label_midi_device.setBounds(20, 20, 200, 20);
		midi_devices_choose = new JComboBox();
		midi_devices_choose.setBounds( 20, 40, 260, 20 );
		topPanel.add(label_midi_device);
		topPanel.add(midi_devices_choose);
		
		
		label_midi_device = new JLabel("Which MIDI-out device to use?");
		label_midi_device.setBounds(20, 60, 200, 20);
		midi_devices_out_choose = new JComboBox();
		midi_devices_out_choose.setBounds( 20, 80, 260, 20 );
		topPanel.add(label_midi_device);
		topPanel.add(midi_devices_out_choose);
		
		
	
		JLabel label_ip_address = new JLabel("Where is NuPlay running at?");
		label_ip_address.setBounds(20,100, 200, 20);
		
		ip_number_choose = new JTextField();
		ip_number_choose.setBounds( 20, 120, 260, 20 );
		try {
			ip_number_choose.setText(InetAddress.getLocalHost().getHostAddress());
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}
		
		topPanel.add(label_ip_address);
		topPanel.add(ip_number_choose);
		
		
		JLabel channel_text = new JLabel("Which channel to use?");
		channel_text.setBounds(20,150, 200, 20);
	
		
		channel = new JComboBox();
		for(int i=0; i < 32;i++) {
			channel.addItem(new Integer(i + 1));
		}
		channel.setBounds( 20, 170, 260, 20 );
		topPanel.add(channel_text);
		topPanel.add(channel);
		
		connect_button = new JButton("Connect to NuPlay.");
		connect_button.addActionListener(this);
		connect_button.setBounds( 20, 210, 200, 20 );
		topPanel.add(connect_button);
		
		error_label = new JLabel("ready...");
		error_label.setForeground(new Color(255,0,0));
		error_label.setBounds(20, 240,200,20);
		topPanel.add(error_label);
		

		java.net.URL imageURL = NuPlayMidiClient.class.getResource("nuplay.png");
		System.out.println(imageURL);
		if (imageURL != null) {
			ImageIcon icon = new ImageIcon(imageURL);
			JLabel image_label = new JLabel(icon);
			this.setIconImage(icon.getImage());
			image_label.setBounds( 260, 195, 50, 77 );
			topPanel.add(image_label);
		}
	}
	
	
	private void init_midi_devices() {
		System.out.println("init_midi_devices");
		try {
	
				MidiDevice.Info[] midi_devices = MidiSystem.getMidiDeviceInfo();
					for(int i = 0; i < midi_devices.length; i++) {
						MidiDevice device = MidiSystem.getMidiDevice(midi_devices[i]);
						System.out.println(device.toString());
						int in_device = device.getMaxReceivers();
						if (in_device != -1) {
							midi_devices_choose.addItem(midi_devices[i].getName());
						} else {
							midi_devices_out_choose.addItem(midi_devices[i].getName());
						}
						
					}
					
					
					
		} catch (Exception e) {
			System.out.println("init_midi_devices");
			e.printStackTrace();
		} 
		if (midi_devices_choose.getItemCount() == 0) {
		//	connect_button.setEnabled(false);
		}
		System.out.println("end");
	}
	
	private void close_midi_device() {
		if (midi_device != null) {
		midi_device.close();
		midi_device = null;
		}
		
	}
	
	private void open_midi_device() {
		
		try {
			sender = new NuPlaySend(this, (Integer)channel.getSelectedItem(), InetAddress.getByName(ip_number_choose.getText()), error_label);
			MidiDevice.Info[] midi_devices = MidiSystem.getMidiDeviceInfo();
				for(int i = 0; i < midi_devices.length; i++) {
					midi_device = MidiSystem.getMidiDevice(midi_devices[i]);
					int in_device = midi_device.getMaxReceivers();
					System.out.println(midi_devices[i].getName());
					if (in_device != -1) {
						if (midi_devices[i].getName().equals(midi_devices_choose.getSelectedItem())) {
							//open midi in
							midi_transmitter = midi_device.getTransmitter();
							midi_transmitter.setReceiver(sender);
							midi_device.open();
										
						}
					} else {
						System.out.println(midi_devices[i].getName());
						if (midi_devices[i].getName().equals(midi_devices_out_choose.getSelectedItem())) {
							
							//open midi out
							System.out.println(midi_device.getMicrosecondPosition());
							midi_receiver = midi_device.getReceiver();
							
							System.out.println("receiver = " + midi_receiver);
							//midi_transmitter.setReceiver(new NuPlaySend((Integer)channel.getSelectedItem(), InetAddress.getByName(ip_number_choose.getText()), error_label));
							midi_device.open();
							
							sender.setMidiOut(midi_receiver);
						
							
						}
					}
				}
	} catch (Exception e) {
		e.printStackTrace();
	} 
		
	}
	public void disconnect(String in_message) {
		connected = false;
		connect_button.setText("Connect to NuPlay.");
		error_label.setText(in_message);
		if (sender != null) {
			sender.close();
			sender = null;
		}
		close_midi_device();
	}
	
	private void connect() {
		connected = true;
		connect_button.setText("Disconnect from NuPlay.");
		error_label.setText("wait for input...");
		open_midi_device();
	}
	
	public void close() {
		System.exit(0);
	}

	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		JFrame main_window = new NuPlayMidiClient();
		main_window.setSize(320, 300);
		main_window.setTitle("NuPlay@Unity3D MIDI client V1.0");
		main_window.setVisible(true);
	}

	public void windowActivated(WindowEvent e) {
		// TODO Auto-generated method stub
		
	}

	public void windowClosed(WindowEvent e) {
		// TODO Auto-generated method stub
		
	}

	public void windowClosing(WindowEvent e) {
		close();
		
	}

	public void windowDeactivated(WindowEvent e) {
		// TODO Auto-generated method stub
		
	}

	public void windowDeiconified(WindowEvent e) {
		// TODO Auto-generated method stub
		
	}

	public void windowIconified(WindowEvent e) {
		// TODO Auto-generated method stub
		
	}

	public void windowOpened(WindowEvent e) {
		// TODO Auto-generated method stub
		
	}
	
}
